# !/usr/bin/python3
# -*- coding:utf-8 -*-
"""
@author: JHC000abc@gmail.com
@file: base_blue.py
@time: 2024/11/5 23:24 
@desc: 

"""
import time
import copy
from functools import wraps
from base import result_tmp
from flask import request, jsonify
from db.model import UserInfo, STATUS_NORMAL, USER_NORMAL
from sdk.utils.util_redis import Redis
from sdk.utils.util_secret import JwtHandler
from config import sk, ak, ACCESS_LIMIT, TIME_WINDOW
from db.db_utils import SqlalchemyDB
from errors.msg import TOKEN, IP,USER

sdb = SqlalchemyDB()
# sk 15分钟有效
jh_sk = JwtHandler(15 * 60, secret=sk)
# ak 15天有效
jh_ak = JwtHandler(15 * 60 * 60 * 24, secret=ak)
redis = Redis()


def get_result_tmp():
    """

    :return:
    """
    return copy.deepcopy(result_tmp)


def get_real_client_ip():
    """

    :return:
    """
    return request.remote_addr


def check_and_update_ip(ip=None, token=None):
    """

    :param ip:
    :param token:
    :return:
    """
    if ip:
        tag = "name"
    else:
        if token:
            tag = "token"
        else:
            return -1

    current_time = int(time.time())

    # 使用 Redis 的键来存储每个 IP 地址的访问计数
    ip_key = f"{tag}:{ip}:count"
    ip_last_time_key = f"{tag}:{ip}:last_time"

    # 获取当前时间戳
    last_time = redis.r.get(ip_last_time_key)

    # 如果是第一次访问，或者超过1分钟，重置计数
    if last_time is None or current_time - int(last_time) > TIME_WINDOW:
        redis.r.set(ip_key, 1, ex=TIME_WINDOW)  # 设置访问计数并设置过期时间
        redis.r.set(ip_last_time_key, current_time, ex=TIME_WINDOW)
        return 1
    else:
        # 否则，增加访问计数
        redis.r.incr(ip_key)
        return int(redis.r.get(ip_key))


# 验证token 装饰器
def auth(func):
    """

    :param func:
    :return:
    """
    result = get_result_tmp()

    @wraps(func)
    def decorated(*args, **kwargs):
        # ip limit check
        ip = get_real_client_ip()
        click_nums = check_and_update_ip(ip)
        if click_nums >= ACCESS_LIMIT:
            result["msg"] = IP["1"].format(ip)
            return jsonify(result)
        headers = request.headers
        client_cookie = headers.get("Authorization")
        if not client_cookie:
            result["msg"] = TOKEN["5"]
            return jsonify(result)
        # token limit check
        click_nums = check_and_update_ip(token=client_cookie)
        if click_nums >= ACCESS_LIMIT:
            result["msg"] = TOKEN["2"].format(client_cookie)
            return jsonify(result)
        client_cookie = client_cookie.split(" ")[-1]
        if redis.check_exists_redis(client_cookie):
            result["msg"] = TOKEN["2"].format(client_cookie)
            return jsonify(result)
        try:
            verify_token = jh_sk.decrypt_token(token=client_cookie)
        except:
            result["msg"] = TOKEN["5"].format(client_cookie)
            return jsonify(result)
        if not verify_token:
            redis.delete_token_redis(client_cookie)
            result["msg"] = TOKEN["1"].format(client_cookie)
            return jsonify(result)
        user_info = jh_sk.parse_token(token=client_cookie)
        db_user_info = sdb.select(UserInfo, {
            "id": user_info["id"],
            "user_name": user_info["user_name"]
        })
        if not db_user_info:
            result["msg"] = USER["4"].format(user_info["user_name"])
            return jsonify(result)
        un_db_user_info = db_user_info[0]
        if un_db_user_info.status != STATUS_NORMAL:
            result["msg"] = USER["7"].format(user_info["user_name"])
            return jsonify(result)
        kwargs['user_info'] = un_db_user_info
        kwargs['cookies'] = client_cookie
        return func(*args, **kwargs)

    return decorated


def auth_manager(func):
    """

    :param func:
    :return:
    """
    result = get_result_tmp()

    @wraps(func)
    def decorated(*args, **kwargs):
        headers = request.headers
        client_cookie = headers.get("Authorization")
        if not client_cookie:
            result["msg"] = TOKEN["5"]
            return jsonify(result)
        client_cookie = client_cookie.split(" ")[-1]
        if redis.check_exists_redis(client_cookie):
            result["msg"] = TOKEN["2"].format(client_cookie)
            return jsonify(result)
        try:
            verify_token = jh_sk.decrypt_token(token=client_cookie)
        except:
            result["msg"] = TOKEN["5"]
            return jsonify(result)
        if not verify_token:
            redis.delete_token_redis(client_cookie)
            result["msg"] = TOKEN["1"].format(client_cookie)
            return jsonify(result)
        user_info = jh_sk.parse_token(token=client_cookie)
        db_user_info = sdb.select(UserInfo, {
            "id": user_info["id"],
            "user_name": user_info["user_name"]
        })
        if not db_user_info:
            result["msg"] = USER["4"].format(user_info["user_name"])
            return jsonify(result)
        un_db_user_info = db_user_info[0]
        if un_db_user_info.status != STATUS_NORMAL:
            result["msg"] = USER["7"].format(user_info["user_name"])
            return jsonify(result)
        if un_db_user_info.grade == USER_NORMAL:
            result["msg"] = USER["1"].format(user_info["user_name"])
            return jsonify(result)
        kwargs['user_info'] = un_db_user_info
        kwargs['cookies'] = client_cookie
        return func(*args, **kwargs)

    return decorated
